%%%-------------------------------------------------------------------
%%% @author liuwentao
%%% @doc
%%%     TCP监听处理
%%% @end
%%% Created : 19. 6月 2021 11:49
%%%-------------------------------------------------------------------
-module(tcp_listener).
-author("liuwentao").

-behaviour(gen_server).


%% 非进程接口
-export([
]).

%% 进程接口
-export([
    start_link/0        %% 进程开启函数
]).


%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

-define(SERVER, ?MODULE).
-include("common.hrl").

-record(state, {}).

%%%===================================================================
%%% API
%%%===================================================================
%% @doc 进程启动
-spec(start_link() ->
    {ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
start_link() ->
    gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).

%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
init([]) ->
    ?INFO("[~w] 正在启动...", [?MODULE]),
    process_flag(trap_exit, true),
    Port = env:get(port),
    case gen_tcp:listen(Port, env:get(tcp_options)) of
        {ok, LSock} ->
            ?INFO("[~w] 成功监听到端口:~w", [?MODULE, Port]),
            start_acceptor(env:get(tcp_acceptor_num), LSock),
            ?INFO("[~w] 启动完成", [?MODULE]),
            {ok, #state{}};
        {error, Reason}->
            ?ERR("[~w] 无法监听到~w:~w", [?MODULE, Port, Reason]),
            {stop, listen_failure, state}
    end.

handle_call(_Request, _From, State) ->
    {noreply, State}.

handle_cast(_Msg, State) ->
    {noreply, State}.

handle_info(_Info, State) ->
    {noreply, State}.

terminate(_Reason, _State) ->
    ?INFO("[~w] 正在关闭...", [?MODULE]),
    ?INFO("[~w] 关闭完成", [?MODULE]),
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

%%----------------------------------------------------
%% 私有函数
%%----------------------------------------------------

start_acceptor(0, _LSock)-> ok;
start_acceptor(N, LSock)->
    supervisor:start_child(tcp_sup, [LSock]),
    start_acceptor(N - 1, LSock).

%%%===================================================================
%%% 工具函数
%%%===================================================================